<!--
 * @Date: 2023-08-17 16:38:04
 * @LastEditors: 景冰川 961166897@qq.com
 * @LastEditTime: 2023-09-07 18:20:36
 * @FilePath: \part-cloud-appd:\project\company\veteran-cadre-app\src\components\register\voice-pop.vue
-->
<script setup lang="ts">
import microIcon from '~/static/images/mine/micro.png'

import { SpeechTranscriptions } from '@/composables/st/st.js'
import { tokens } from '@/composables/st/token.js'
import { encodeWAV, isEmpty } from '@/util/utils'
import { BASE_URL } from '@/api/request'
import { useAppStore } from '@/stores/app-store'

const props = defineProps({
  title: {
    type: String,
    default: '普通话',
  },
  showSonicView: {
    type: Boolean,
    default: true,
  },
})
const emit = defineEmits(['onOpen', 'onClose', 'onSelectText'])
const appstore = useAppStore()

const text = ref('')
const popupRef = ref(null)
const sts = ref(null)
const audioUrl = ref('')
const useAudio = ref(true)

const recoderAuthStatus = ref(false) // 录音授权状态
const srStart = ref(false)

const showSelectIcon = computed(() => {
  return text.value || audioUrl.value
})
function open() {
  getAuthSetting()
  yy()
  popupRef.value.open('bottom')
  emit('onOpen')
}
function close() {
  text.value = ''
  audioUrl.value = ''
  try {
    appstore.state.recorderManager.stop()
  }
  catch (error) {

  }
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-expect-error
  uni.hideLoading({ success: () => {} })
  popupRef.value.close()
  // onStStop()
  emit('onClose')
}
onShow(() => {
  // appstore.state.recorderManager = uni.getRecorderManager()
  // yy()
})
onUnload(() => {
  srStart.value = false
  if (srStart.value)
    appstore.state.recorderManager.stop()
  if (sts.value)
    sts.value.shutdown()
})

function getAuthSetting() {
  uni.getSetting({
    success(res) {
      if (!res.authSetting['scope.record']) {
        uni.authorize({
          scope: 'scope.record',
          success() {
            recoderAuthStatus.value = true
          },
          fail() {
            recoderAuthStatus.value = false
          },
        })
      }
      else {
        recoderAuthStatus.value = true
      }
    },
  })
}

async function yy() {
  appstore.state.recorderManager.onFrameRecorded((res) => {
    if (sts.value && srStart.value)
      sts.value.sendAudio(res.frameBuffer)
    // sts.value.stop()
  })
  appstore.state.recorderManager.onStart(() => {
    useAudio.value = true
    uni.showLoading({
      title: '请说话说完松手',
      mask: false,
    })
  })
  appstore.state.recorderManager.onStop((res) => {
    const tempFilePath = res.tempFilePath // 音频文件地址
    if (useAudio.value === false) {
      if (tempFilePath) {
        uni
          .getFileSystemManager()
          .removeSavedFile({ filePath: res.tempFilePath })
      }
      return
    }
    const FileSystemManager = uni.getFileSystemManager()
    FileSystemManager.readFile({
      filePath: tempFilePath,
      success: (res) => {
        const view = encodeWAV(res.data, 1, 16000)
        const dateNow = Date.now()
        const path = `${wx.env.USER_DATA_PATH}/${dateNow}.wav`
        FileSystemManager.writeFile({
          data: view.buffer,
          filePath: path,
          success: (res2) => {
            // 拿封装好的文件进行操作

            uni.uploadFile({
              url: `${BASE_URL}/app/appConfig/upload`, // 仅为示例，非真实的接口地址
              filePath: path,
              name: 'file',
              formData: {
                user: 'test',
              },
              success: (uploadFileRes) => {
                const fileUrl = JSON.parse(uploadFileRes.data).data.url
                audioUrl.value = fileUrl

                if (tempFilePath) {
                  uni
                    .getFileSystemManager()
                    .removeSavedFile({ filePath: tempFilePath })
                }
                uni.getFileSystemManager().removeSavedFile({ filePath: path })
              },
              fail: (e) => {
                // uni.hideLoading()
              },
            })
          },
        })
      },
    })
  })
  appstore.state.recorderManager.onError((res) => {
    console.error(`录音异常:${JSON.stringify(res)}`)
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-expect-error
    uni.hideLoading({ success: () => {} })
    useAudio.value = false
  })

  const AKID = 'LTAI5tGA1EaygTTFg1k2aXx6'
  const AKKEY = 'XwvACRSv98qpBdRJQkPpmLTL3VF74K'

  const token = await tokens.getToken(AKID, AKKEY).catch((err) => {
    console.error(err)
  })
  const st = new SpeechTranscriptions({
    url: 'wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1',
    appkey: 'vKSjIvpHbOjNZJVi',
    token,
  })

  st.on('started', (msg) => {})

  st.on('changed', (msg) => {
    const msgs = JSON.parse(msg).payload.result
    console.error('changed', msgs)
    text.value = msgs
  })

  st.on('completed', (msg) => {
    const msgs = JSON.parse(msg).payload.result
    console.error('completed', msgs)
  })

  st.on('begin', (msg) => {
    const msgs = JSON.parse(msg).payload.result
    console.error('begin', msgs)
  })

  st.on('end', (msg) => {
    const msgs = JSON.parse(msg).payload.result
    console.error('end', msgs)
    // text.value += msgs
  })

  st.on('closed', () => {
    console.error('closed')
  })

  st.on('failed', (msg) => {
    console.error(`msg:${msg}`)
    // onStStop()
  })
  sts.value = st
}

async function onStStart() {
  doThing()
  async function doThing() {
    if (!sts.value)
      return
    if (srStart.value)
      return
    if (!isEmpty(text.value) || !isEmpty(audioUrl.value)) {
      text.value = ''
      audioUrl.value = ''
    }
    const sr = sts.value
    const format = 'PCM'
    try {
    // sr.defaultStartParams()
      await sr.start({
        appkey: 'vKSjIvpHbOjNZJVi',
        format,
        sample_rate: 16000,
        enable_intermediate_result: true,
        enable_punctuation_prediction: true,
        enable_inverse_text_normalization: true,
        enable_semantic_sentence_detection: true,
        max_sentence_silence: 6000,
        enable_ignore_sentence_timeout: true,
      })
      srStart.value = true
    }
    catch (e) {
      console.error(`start st${JSON.stringify(e)}`)
      return
    }

    appstore.state.recorderManager.start({
      duration: 600000,
      numberOfChannels: 1,
      sampleRate: 16000,
      format,
      frameSize: 4,
    })
  }
}

async function onStStop() {
  appstore.state.recorderManager.stop()
  srStart.value = false

  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-expect-error
  uni.hideLoading({ success: () => {} })
  try {
    if (srStart.value && sts.value)
      await sts.value.close()
  }
  catch (e) {
    console.error(`err: ${e}`)
  }
}

async function onSelectText() {
  if (!text.value) {
    uni.showToast({
      title: '请说一些内容吧',
      icon: 'none',
    })
    return
  }
  emit('onSelectText', {
    text: text.value,
    audioUrl: audioUrl.value,
  })
}

async function onSelectTextClose() {
  text.value = ''
  audioUrl.value = ''
}
defineExpose({
  open,
  close,
})
</script>

<template>
  <uni-popup ref="popupRef" background-color="white" @mask-click="close">
    <view class="popup-content">
      <div class="pb-20rpx pt-32rpx flex relative">
        <div class="text-40rpx text-center text-#333 flex-1">
          {{ props.title }}
        </div>
        <uni-icons
          class="absolute right-32rpx top-32rpx"
          color="rgba(153,153,153,0.451)"
          type="clear"
          size="32"
          @click="close"
        />
      </div>
      <div class="mx-a border-1px border-#F6F6F6 border-solid h-0 w-686rpx" />
      <textarea
        v-model="text"
        class="pl-20rpx pt-20rpx mx-a mb-40rpx mt-32rpx bg-#F6F6F6 text-#666 h-200rpx min-h-200rpx w-686rpx"
        :maxlength="-1"
        placeholder-style="color:#999"
        :disabled="false"
        auto-height
        placeholder="请说出要输入的文字"
      />
      <view v-if="props.showSonicView" class="mb-80rpx">
        <sonic-view v-if="audioUrl" :audio-url="audioUrl" />
      </view>

      <div class="mb-62rpx center">
        <uni-icons
          v-if="showSelectIcon"
          class="mr-50rpx"
          type="closeempty"
          size="40"
          color="#999"
          @click="onSelectTextClose"
        />
        <!-- style="pointer-events: none" -->
        <!--
          @touchstart.stop.prevent="onStStart" -->
        <button
          :style="{ pointerEvents: !sts ? 'none' : 'painted' }"
          :disabled="!sts"
          class="cir-btn m-0 bg-#24997E rounded-full center flex h-216rpx w-216rpx"
          :class="[srStart ? 'animation-play' : 'animation-paused']"
          @touchstart.stop.prevent="onStStart"
          @touchend="onStStop"
        >
          <image
            class="block h-96rpx w-96rpx"
            :src="microIcon"
            mode="scaleToFill"
          />
        </button>
        <uni-icons
          v-if="showSelectIcon"
          class="ml-50rpx"
          type="checkmarkempty"
          size="40"
          color="#4FAE98"
          @click="onSelectText"
        />
      </div>
      <view class="my-10rpx text-center text-black">
        请按住说话
      </view>
    </view>
  </uni-popup>
</template>

<style lang="scss" scoped>
.popup-content {
  background-color: white;
}
.button {
  width: 362rpx;
  height: 80rpx;
  margin-top: 40rpx;
  line-height: 80rpx;
  border-radius: 60rpx;
  display: flex;
  flex-direction: column;
  background: linear-gradient(282deg, #ff8f1f -3%, #ff1a01 99%);
  font-size: 28rpx;
  font-weight: 500;
  letter-spacing: 0.1em;
  color: #ffffff;
}
.sonic {
  // border: 1px solid red;
  padding-bottom: 60rpx;
}
.cir-btn{
  position: relative;
}

@keyframes neiquan {
  from {
      transform: scale(0.5)
  }
  to {
      transform: scale(1)
  }
}
.animation-play {
  &::after {
    opacity: 0.7;
    transform-origin: 108rpx 108rpx;
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    background-color: #66CCCC;
    animation-name: neiquan;
    animation-duration: 1s;
    animation-iteration-count: infinite;
    /* 动画执行的方向 */
    animation-direction: reverse;
    /* 交替执行 */
    animation-direction: alternate;
    animation-play-state: running !important;
  }
}
.animation-paused {
  &::after {
    animation-play-state: paused !important;
  }
  animation-play-state: paused !important;
}
</style>
